#pragma once
#ifndef __REQUEST_H__
#define __REQUEST_H__


#include <vector>
#include <memory>
#include <span>
#include <netinet/in.h>
#include <string.h>
#include <any>
#include <msg/message.h>
#include <util/forward_rule.h>

enum class request_op : uint32_t {
    LOG_IN, 
    LOG_OUT, 
    REGISTER,
    CREATE_FORWARD_RULE,
    CRAETE_OUTPUT_FORWARD_RULE,
    CREATE_VIRTUAL_CLIENT,

    DELETE_FORWARD_RULE,
    DELETE_OUTPUT_FORWARD_RULE,
    DELETE_VIRTUAL_CLIENT
};


struct create_output_forward_rule_data{
    uint32_t user;
    uint32_t host;
    uint32_t rule_id;
    uint32_t target_ip;
    uint16_t target_port;
    void transform_to_network_byte_order()  {

    }
    void transform_to_host_byte_order()  {

    } 
};




struct create_virtual_client_data{
    uint32_t user;
    uint32_t host;
    uint32_t rule_id;
    uint32_t app_id;
    create_virtual_client_data() = default;
    create_virtual_client_data(uint32_t user, uint32_t host, uint32_t rule_id, uint32_t app_id){
        this->user = user;
        this->host = host;
        this->rule_id = rule_id;
        this->app_id = app_id;
    }
    void transform_to_network_byte_order() {

    }
    void transform_to_host_byte_order() {

    } 
};
using delete_virtual_client_data = create_virtual_client_data;


struct alignas(32) request_head{
    request_op op;
    uint32_t req_id;
    void transform_to_network_byte_order() {

    }
    void transform_to_host_byte_order() {

    } 
};


struct request : message{
    request(){
        set_message_type(MessageType::REQUEST);
    }

    request(message msg){
        *static_cast<message*>(this) = msg;
    }

    request_head get_head(){
        request_head head = *get_head_ptr();
        head.transform_to_host_byte_order();
        return head;
    }

    void set_head(request_head head){
        head.transform_to_network_byte_order();
        set_content(0, &head, sizeof(head));
        // *get_head_ptr() = head;
    }

    std::any get_body(){
        switch (get_head().op)
        {
            using enum request_op;
        case LOG_IN:{
            std::string password(reinterpret_cast<char*>(get_body_ptr()), get_body_size());
            return password;
        }
        case CREATE_FORWARD_RULE:{
            forward_rule rule_net_order = *reinterpret_cast<forward_rule*>(get_body_ptr());
            rule_net_order.transform_to_host_byte_order();
            return rule_net_order;
        }
        case CRAETE_OUTPUT_FORWARD_RULE:{
            create_output_forward_rule_data rule_net_order = *reinterpret_cast<create_output_forward_rule_data*>(get_body_ptr());
            rule_net_order.transform_to_host_byte_order();
            return rule_net_order;
        }
        case CREATE_VIRTUAL_CLIENT:{
            create_virtual_client_data data = *reinterpret_cast<create_virtual_client_data*>(get_body_ptr());
            data.transform_to_host_byte_order();
            return data;
        }
        }
        return {};
    }

    void set_body(void* ptr, uint32_t size){
        set_content(REQUEST_HEAD_SIZE, ptr, size);
    }

    size_t get_body_size(){
        return get_router_info().data_size - REQUEST_HEAD_SIZE;
    }

protected:
    request_head* get_head_ptr(){
        return reinterpret_cast<request_head*>(get_content_ptr(0));
    }

    void* get_body_ptr(){
        return get_content_ptr(REQUEST_HEAD_SIZE);
    }

private:
    static const size_t REQUEST_HEAD_SIZE = sizeof(request_head);
};

#endif // __REQUEST_H__